/* GL Camera
 *
 * Thanks go out to Alexander Festini for his OpenGL
 * Camera implementation.
 */

#include "camera.h"

#include <string.h>

Camera::Camera( const GLfloat p_X, const GLfloat p_Y, const GLfloat p_Z )
{
	memset( m_Transform, 0, 16 * sizeof( float ) );

	m_Transform[0]  = 1.0f;
	m_Transform[5]  = 1.0f;
	m_Transform[10] = -1.0f;
	m_Transform[15] = 1.0f;
	m_Transform[12] = p_X;
	m_Transform[13] = p_Y;
	m_Transform[14] = p_Z;

	g_Right    =& m_Transform[0];
	g_Up 	   =& m_Transform[4];
	g_Forward  =& m_Transform[8];
	g_Position =& m_Transform[12];
}

Camera::~Camera()
{
	delete[] m_Transform;
}

void Camera::SetView( void )
{
	glMatrixMode( GL_MODELVIEW );
	glLoadIdentity();

	float m[16] = {
		m_Transform[0], m_Transform[4], -m_Transform[8], 0,
		m_Transform[1], m_Transform[5], -m_Transform[9], 0,
		m_Transform[2], m_Transform[6], -m_Transform[10], 0,

		-(m_Transform[0] * m_Transform[12] +
		m_Transform[1]   * m_Transform[13] +
		m_Transform[2]   * m_Transform[14]),

		-(m_Transform[4] * m_Transform[12] +
		m_Transform[5]   * m_Transform[13] +
		m_Transform[6]   * m_Transform[14]),

		(m_Transform[8] * m_Transform[12] +
		m_Transform[9]  * m_Transform[13] +
		m_Transform[10] * m_Transform[14]), 1
	};

	glLoadMatrixf( m );
}

void Camera::MoveLoc( GLfloat p_X, GLfloat p_Y, GLfloat p_Z, GLfloat p_Distance )
{
	float dX = p_X * m_Transform[0] + p_Y * m_Transform[4] + p_Z * m_Transform[8];
	float dY = p_X * m_Transform[1] + p_Y * m_Transform[5] + p_Z * m_Transform[9];
	float dZ = p_X * m_Transform[2] + p_Y * m_Transform[6] + p_Z * m_Transform[10];

	m_Transform[12] += dX * p_Distance;
	m_Transform[13] += dY * p_Distance;
	m_Transform[14] += dZ * p_Distance;
}

void Camera::MoveGlob( GLfloat p_X, GLfloat p_Y, GLfloat p_Z, GLfloat p_Distance )
{
	m_Transform[12] += p_X * p_Distance;
	m_Transform[13] += p_Y * p_Distance;
	m_Transform[14] += p_Z * p_Distance;
}

void Camera::RotateLoc( GLfloat p_Degrees, GLfloat p_X, GLfloat p_Y, GLfloat p_Z )
{
	glMatrixMode( GL_MODELVIEW );
	glPushMatrix();
		glLoadMatrixf( m_Transform);
		glRotatef( p_Degrees, p_X, p_Y, p_Z );
		glGetFloatv( GL_MODELVIEW_MATRIX, m_Transform );
	glPopMatrix();
}

void Camera::RotateGlob( GLfloat p_Degrees, GLfloat p_X, GLfloat p_Y, GLfloat p_Z )
{
	float dX = p_X * m_Transform[0] + p_Y * m_Transform[1] + p_Z * m_Transform[2];
	float dY = p_X * m_Transform[4] + p_Y * m_Transform[5] + p_Z * m_Transform[6];
	float dZ = p_X * m_Transform[8] + p_Y * m_Transform[9] + p_Z * m_Transform[10];

	glMatrixMode( GL_MODELVIEW );
	glPushMatrix();
		glLoadMatrixf( m_Transform );
		glRotatef( p_Degrees, dX, dY, dZ );
		glGetFloatv( GL_MODELVIEW_MATRIX, m_Transform );
	glPopMatrix();
}
